/* 
 * File:   ShaderItem.cpp
 * Author: ferranferri
 * 
 * Created on May 30, 2013, 5:47 PM
 */
#include <GL/glew.h>
#include <GL/glfw.h>
#include "ShaderItem.h"
#include "../internal/engine_constants.h"
#include "../utils/glUtils.h"
#include <iterator>
#include <GL/glext.h>

namespace z3d{
    ShaderItem::ShaderItem(const std::string& name, const std::string& fileName, GLenum type)
        :_name(name)
        ,_source(NULL)
        ,_filename(fileName)
        ,_type(type)
        ,_handle(0)
        ,_debugState(false)
        ,_compiled(true)
        ,_refCount(0)
        ,_log(NULL)
    {
    }
    
    bool ShaderItem::init() {
        _log = &glog::CGlobalLog::getSingleton();
        
        _compiled = false;
        _debugState = true;
        _refCount = 0;
        
        // cargar fichero
        _log->DEBUG_MSG(Z3D_APPENDER, "Loading shader file %s wit name %s", _filename.c_str(), _name.c_str());
        std::ifstream shaderCode(_filename.c_str());
        if(!shaderCode.good())
        {
            _log->ERROR_MSG(Z3D_APPENDER, "Unable to load shader file %s", _filename.c_str());
            return false;
        }
        _source = new std::string(std::istreambuf_iterator<char>(shaderCode), std::istreambuf_iterator<char>());
        shaderCode.close();
        *_source +="\0";

        return true;
    }
    
    bool ShaderItem::load() {
        // primero, adquirir un handle de shader 
        /*
        switch (_type)
        {
          case ST_VERTEX : { _handle = glCreateShader(GL_VERTEX_SHADER); break; }
          case ST_FRAGMENT : { _handle = glCreateShader(GL_FRAGMENT_SHADER); break; }
          case ST_GEOMETRY : { _handle = glCreateShader(GL_GEOMETRY_SHADER); break; }
          default:
              THROW_AND_LOG(Z3D_APPENDER, z3d::core::IncorrectOptionException, "The current option is incorrect.");
        }
        */ 
        _handle = glCreateShader(_type);
        CHECK_OPENGL_ERROR
        
        const char* srcCode = _source->c_str();
        glShaderSource(_handle, 1, &srcCode, NULL);
        CHECK_OPENGL_ERROR
                
        _log->DEBUG_MSG(Z3D_APPENDER, "Loaded shader %s with handle %d", _name.c_str(), _handle);
        // TODO: Se deberia borrar el codigo fuente?
        
        _compiled = false;
        
        return compile();
    }
    
    bool ShaderItem::compile() {
        if(_source == 0) {
            THROW_AND_LOG(Z3D_APPENDER, z3d::core::resourceManagementException, "Shader source is empty!");
        }
        _log->DEBUG_MSG(Z3D_APPENDER, "Compiling shader %s", _name.c_str());
        glCompileShader(_handle);
        CHECK_OPENGL_ERROR
        _compiled = true;
        return true;
    }
    
    bool ShaderItem::unload() {
        _log->DEBUG_MSG(Z3D_APPENDER, "Destroying shader %s with handle %d", _name.c_str(), _handle);
        glDeleteShader(_handle);
        CHECK_OPENGL_ERROR
        _compiled = false;
        return true;
    }
    
    ShaderItem::~ShaderItem() {
        
    }
}